﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace ebc.minibus.tests
{
    [TestFixture]
    public class usage_scenario
    {
        [Test]
        public void Run_demo_process()
        {
            var bus = new EbcMiniBus();

            var scatter = new Scatterer<string>();
            var gather = new Gatherer<int>();
    
            bus.Register<int, IEnumerable<string>>(n =>
                                                       {
                                                           var items = new List<string>();
                                                           var x = 1;
                                                           for(var i=1; i<=n; i++, x *= 10)
                                                               items.Add(x.ToString());
                                                           return items;
                                                       }, "generate items");
            
            bus.Register<IEnumerable<string>>(scatter.ScatterThis);
            scatter.ScatteredItem += _ => bus.Send(_, "process item");
            scatter.NumberOfScatteredItems += _ => bus.Send(_, "numbers of items scattered");

            bus.Register<string, int>(s => s.Length, "process item", "item to gather");

            bus.Register<int>(gather.NumberOfScatteredItems, "numbers of items scattered");
            bus.Register<int>(gather.ItemToGather, "item to gather");
            gather.GatheredItems += _ => bus.Send(_);

            var total = 0;
            bus.Register<IEnumerable<int>>(items => total = items.Sum());

            bus.Send(5, "generate items");

            Assert.AreEqual(15, total);
        }


        class Scatterer<T>
        {
            public void ScatterThis(IEnumerable<T> items)
            {
                var itemArray = items.ToArray();
                this.NumberOfScatteredItems(itemArray.Length);
                foreach (var item in itemArray)
                    this.ScatteredItem(item);
            }

            public event Action<T> ScatteredItem;
            public event Action<int> NumberOfScatteredItems;
        }


        class Gatherer<T>
        {
            private int maxCount;
            private List<T> items = new List<T>();

            public void NumberOfScatteredItems(int maxCount)
            {
                this.maxCount = maxCount;
            }

            public void ItemToGather(T item)
            {
                this.items.Add(item);
                if (this.items.Count >= this.maxCount)
                {
                    this.GatheredItems(this.items);
                    this.items = new List<T>();
                }
            }

            public event Action<IEnumerable<T>> GatheredItems;
        }
    }
}
